"""
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    created by lei.chang on '23/04/2023'
    comment: 流程节点相关
"""
from datetime import datetime
from datetime import timedelta
from sqlalchemy import func
from sqlalchemy.dialects.mysql import VARCHAR, INTEGER, DATETIME, TIMESTAMP, BOOLEAN, FLOAT

from project.core.base import CustomModel, CustomDict, CustomList
from project.core.base import Column


class Node(CustomModel):
    """ 节点表
    """
    __tablename__ = "node"
    id = Column(INTEGER(unsigned=True), primary_key=True, autoincrement=True)
    code = Column(VARCHAR(30), nullable=False, server_default='', comment='节点编号')
    name = Column(VARCHAR(30), nullable=False, server_default='', comment='节点名称')
    node_type = Column(VARCHAR(30), nullable=False, server_default='', comment='节点类型(来源于node_type表)')
    title = Column(VARCHAR(100), nullable=False, server_default='', comment='标题')
    introduction = Column(VARCHAR(200), nullable=False, server_default='', comment='节点介绍')
    business_type = Column(VARCHAR(30), nullable=False, server_default='', comment='业务类型 catering(餐饮)/shopping(购物)/other(其它)')
    button_text = Column(VARCHAR(30), nullable=False, server_default='', comment='按钮文本')
    display_text = Column(VARCHAR(600), nullable=False, server_default='', comment='文本展示（200字以内）')
    timeset = Column(CustomDict(1000), nullable=False, server_default='', comment='时间设置 {"dates": ["today", "tomorrow", "after_tomorrow"], "meal_period": {"start_time": xxx, "end_time": xxx}, "interval": 60(单位分钟)}')
    phone_type = Column(VARCHAR(30), nullable=False, server_default='', comment='手机号类型 eleven_bit(11位)/last_four_bit(后四位)')
    title_icon = Column(VARCHAR(200), nullable=False, server_default='', comment='内容图标')
    invoice_types = Column(CustomList(30), nullable=False, server_default='', comment='发票类型: electronic(电子发票)/paper(纸质发票)')
    is_first = Column(BOOLEAN, nullable=False, server_default='0', comment='是否第一个节点')
    next_node_id = Column(INTEGER(unsigned=True), nullable=False, server_default='0', comment='下一节点id')
    select_mode = Column(VARCHAR(20), nullable=False, server_default='single', comment='选择方式: single(单选)/multiple(多选)')
    is_group = Column(BOOLEAN, nullable=False, server_default='0', comment='是否需要分组 0: 不需要 1：需要')
    flow_id = Column(INTEGER(unsigned=True), nullable=False, server_default='0', comment='服务流程id')
    flow_code = Column(VARCHAR(30), nullable=False, server_default='', comment='服务流程编号')
    is_send_sms = Column(BOOLEAN, nullable=False, server_default='0', comment='是否需要发送短信 0: 不需要 1：需要')
    sms_greet = Column(VARCHAR(35), nullable=False, server_default='', comment='短信问候语')

    is_display_reducible = Column(BOOLEAN, nullable=False, server_default='0', comment='是否展示可约量 0:否 1:是')
    is_display_calendar = Column(BOOLEAN, nullable=False, server_default='0', comment='是否显示日历 0:否 1:是')
    time_mode = Column(VARCHAR(30), nullable=False, server_default='', comment='时间模式 period(时间段)/point(时间点)')
    time_periods = Column(CustomList(500), nullable=False, server_default='', comment='时间段 例如: 07:00~08:00')
    time_interval = Column(INTEGER(unsigned=True), nullable=False, server_default='0', comment='间隔时间(分钟)')
    time_durations = Column(CustomList(500), nullable=False, server_default='', comment='时长列表')

    is_deleted = Column(BOOLEAN, nullable=False, server_default='0', comment='是否删除 0: 未删除 1: 已删除', is_displayed=False)
    create_time = Column(DATETIME, nullable=False, server_default=func.now(), is_displayed=False)
    update_time = Column(TIMESTAMP, nullable=False, server_default=func.now(), onupdate=func.now(), is_displayed=False)

    @staticmethod
    def _get_periods(start_time, end_time, interval):
        """
        :param start_time:
        :param end_time:
        :param interval:
        :return:
        """
        _periods = []
        if interval:
            # 根据当前时间筛选时间段
            _start_time = start_time
            while True:
                _end_time = _start_time + timedelta(minutes=interval)
                if _end_time >= end_time:
                    _periods.append({'title': f'{_start_time.strftime("%H:%M")}~{end_time.strftime("%H:%M")}'})
                    break

                _periods.append({'title': f'{_start_time.strftime("%H:%M")}~{_end_time.strftime("%H:%M")}'})
                _start_time = _end_time
        else:
            _periods.append({'title': f'{start_time.strftime("%H:%M")}~{end_time.strftime("%H:%M")}'})

        return _periods

    @property
    def meal_periods(self):
        """ 时间段
        :return:
        """
        periods = []
        if self.timeset:
            meal_period = self.timeset.get('meal_period', {})
            start_time = meal_period.get('start_time') or '00:00'
            start_time = datetime.strptime(start_time, '%H:%M')
            end_time = meal_period.get('end_time') or '23:59'
            end_time = datetime.strptime(end_time, '%H:%M')
            interval = self.timeset.get('interval')
            periods.extend(self.__class__._get_periods(start_time, end_time, interval))
        else:
            if not self.time_periods:
                return periods
            for v in self.time_periods:
                start_time = datetime.strptime(v['start_time'], '%H:%M')
                end_time = datetime.strptime(v['end_time'], '%H:%M')
                periods.extend(self.__class__._get_periods(start_time, end_time, self.time_interval))

        return periods

    @property
    def meal_periods_filtered(self):
        """
        :return:
        """
        periods = []
        if not self.timeset:
            return periods

        now_minute = datetime.now().strftime('%H:%M')
        today_meal_periods = [v for v in self.meal_periods if v['title'][0:5] > now_minute]

        for v in self.timeset.get('dates', []):
            if v == 'today':
                if not today_meal_periods:
                    continue

                periods.append({
                    'date': v,
                    'meal_periods': today_meal_periods
                })
            else:
                periods.append({
                    'date': v,
                    'meal_periods': self.meal_periods
                })

        return periods


class NodeGroup(CustomModel):
    """ 节点分组表
    """
    __tablename__ = "node_group"
    id = Column(INTEGER(unsigned=True), primary_key=True, autoincrement=True)
    title = Column(VARCHAR(30), nullable=False, server_default='', comment='组名')
    image = Column(VARCHAR(200), nullable=False, server_default='', comment='组图片')
    meal_period = Column(CustomDict(200), nullable=False, server_default='', comment='餐段 {"start_time": xxx, "end_time": xxx}')
    node_id = Column(INTEGER(unsigned=True), nullable=False, server_default='0', comment='节点id')
    is_deleted = Column(BOOLEAN, nullable=False, server_default='0', comment='是否删除 0: 未删除 1: 已删除', is_displayed=False)
    create_time = Column(DATETIME, nullable=False, server_default=func.now(), is_displayed=False)
    update_time = Column(TIMESTAMP, nullable=False, server_default=func.now(), onupdate=func.now(), is_displayed=False)


class NodeItem(CustomModel):
    """ 节点项目表
    """
    __tablename__ = "node_item"
    id = Column(INTEGER(unsigned=True), primary_key=True, autoincrement=True)
    title = Column(VARCHAR(30), nullable=False, server_default='', comment='项目名称')
    content = Column(VARCHAR(200), nullable=True, comment='项目说明')
    image = Column(VARCHAR(500), nullable=True, comment='图片(oss)')
    count = Column(INTEGER(unsigned=True), nullable=True, comment='数量')
    price = Column(FLOAT, nullable=True, comment='单价')
    detail = Column(CustomList(2000), nullable=True, comment='详情 [{"audio": "", "image": "", "content": ""}, {"audio": "", "image": "", "content": ""}]')
    count_upper_limit = Column(INTEGER(unsigned=True), nullable=True, comment='数量上限')
    is_count = Column(BOOLEAN, nullable=False, server_default='0', comment='是否可选择数量 默认: 0')
    is_spec = Column(BOOLEAN, nullable=False, server_default='0', comment='是否可选择规格 默认: 0')
    spec = Column(CustomList(2000), comment='规格信息 [{"title": xxx, "items": [xxx, xxx, xxx]}, {"title": xxx, "items": [xxx, xxx, xxx]}]')
    node_id = Column(INTEGER(unsigned=True), nullable=False, server_default='0', comment='节点id')
    group_id = Column(INTEGER(unsigned=True), nullable=False, server_default='0', comment='分组id')
    is_deleted = Column(BOOLEAN, nullable=False, server_default='0', comment='是否删除 0: 未删除 1: 已删除', is_displayed=False)
    create_time = Column(DATETIME, nullable=False, server_default=func.now(), is_displayed=False)
    update_time = Column(TIMESTAMP, nullable=False, server_default=func.now(), onupdate=func.now(), is_displayed=False)
